package language.advanced.Concurrent;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

//使用阻塞队列处理生产者消费者问题
public class FutureWriteExcelTest {
    private static final BlockingQueue<List<User>> bQueue = new LinkedBlockingQueue<>(3);

    private static final int CORE_POOL_SIZE = 5;
    private static final int MAX_POOL_SIZE = 10;
    private static final int QUEUE_CAPACITY = 100;
    private static final Long KEEP_ALIVE_TIME = 1L;
    public static final Random random = new Random(47);

    private static final int page = 40;

    public static ArrayList<User> single(){
//        System.out.println("single 执行: "+ Thread.currentThread().getName());
        int i = random.nextInt();
        ArrayList<User> users = new ArrayList<>();
        User user = new User();
        user.setUsername("a:" + i);
        user.setBirthday(new Date());
        users.add(user);
        return users;
    }

    @Test
    public void ddd(){
        ExcelWriter excel = EasyExcel.write("exportOutMultiBatch.xlsx", User.class).build();
        WriteSheet sheet = EasyExcel.writerSheet("sheetExample").build();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(QUEUE_CAPACITY), new ThreadPoolExecutor.CallerRunsPolicy());
        System.out.println("ddd 执行: "+ Thread.currentThread().getName());

        for (int i = 0; i < page; i++) {
            CompletableFuture.supplyAsync(FutureWriteExcelTest::single, executor)
                    .whenComplete((res,err) -> {
//                        System.out.println("whenComplete 执行: "+ Thread.currentThread().getName());
                        excel.write(res, sheet);
                    });
        }

        // 关闭线程池executor
        // 说明一下executor必须要显示关闭（它的方法里有介绍），不然线程池会一直等待任务，会导致main方法一直运行
        // 还有就是关闭executor，不会导致之前提交的异步任务被打断或者取消。即之前提交的任务依然会执行到底，只是不会再接收新的任务
        executor.shutdown();

        /* 那么关闭线程池之后，我们怎么确定我们的任务是否都完成了呢，可以使用executor.isTerminated()命令
        // 可以看看isTerminated这个方法的说明，简单的说就是调用isTerminated()方法之前没有调用shutdown()方法的话，那么isTerminated()方法返回的永远是false。
        // 所以isTerminated()方法返回true的情况就是在调用isTerminated()方法之前要先调用shutdown()方法，且所有的任务都完成了。
        // 其实调用isTerminated()的目的就是我们对异步任务的结果是care, 我们需要等待异步任务的结果以便我们做下一步的动作。
        // 如果我们不关心异步任务的结果的话，完全可以不用调用isTerminated()。
        */
        while (!executor.isTerminated()) {
            System.out.println("no terminated");
            try {
                System.out.println("我要休眠一下");
                TimeUnit.MILLISECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        excel.finish();

    }
}


//@Data
//class User {
//
//    @ExcelProperty("用户名")
//    private String username;
//    @ExcelProperty("生日")
//    private Date birthday;
//}

